// Copyright(c) Sonosemi Medical Ltd. Embedded Software Team.
// Author: Zhang Yisong(zhangyisong@sonosemi.com)

#pragma once

#include "internal/active_active.hpp"
#include <tuple>
#include <type_traits>

namespace active {
namespace internal {

template <typename T> struct is_active_config : public std::false_type {};

template <typename... Ts>
struct is_active_config<internal::Active<Ts...>> : public std::true_type {};

template <typename... Ts>
struct is_active_config<const internal::Active<Ts...>> : public std::true_type {};

template <typename T> struct is_active_tuple : public std::false_type {};

template <typename... Ts>
  requires std::conjunction_v<is_active_config<std::remove_cv_t<Ts>>...>
struct is_active_tuple<std::tuple<Ts...>> : public std::true_type {};

template <typename... Ts>
  requires std::conjunction_v<is_active_config<std::remove_cv_t<Ts>>...>
struct is_active_tuple<const std::tuple<Ts...>> : public std::true_type {};
} // namespace internal

namespace concepts {

template <typename T>
concept ActiveConfiguable =
    std::disjunction<internal::is_active_config<T>,
                     internal::is_active_tuple<T>>::value;

}

} // namespace active